function qvPaired(varargin)
% qvPaired
%
% For browsing ephus traces (*.xsg files).
%
% If called with no input argument, or 'init', it will go to the
%   default directory (specified below) and ask you to select
%   a file. If called with 'init' and and valid path name as 
%   arguments, it will go to that directory before prompting.
%
% Example: qvPaired('init', 'C:\_Data')
%
% Notes: data made available as 'currentTrace' variable in the workspace

% TODO:
%   Option to hold display to accumulate traces

% editing:
% gs dec 2007 -- Adapted from quickViewTrace
% taro Kiritani aug 2009 --- adapted from qvTrace
% tk jan 2010 -- add specific mode.
% tk jul 2010 -- arbitrary number of traces are now acceppted.
% tk oct 2010 -- can chose the fcn shows the entire traces or only some timeframe
% ----------------------------------------------------

defaultDirectory = 'C:\Data';

if nargin == 0 || strcmp(varargin{1}, 'init')
    mode = 'init';
    if nargin < 2
    elseif nargin >1 && ~isempty(varargin{2})
        defaultDirectory = varargin{2};
    end
else
    mode = varargin{1};
end

switch mode
    case 'init'
        data = [];
        try
            cd(defaultDirectory);
        catch
            try
                cd('C:\DATA\Taro\CELLS');
            catch
%                 disp('qvTrace: unable to find default dir.')
            end
        end
        [filename, pathname] = uigetfile('*.xsg', 'Select an XSG trace');
        if isequal(filename,0) || isequal(pathname,0)
            return
        end
        fullfilename = fullfile(pathname, filename);
        [pathstr, tracename, ext, versn] = fileparts(fullfilename);
        data.completename = fullfile(pathstr, [tracename, ext, versn]);
        data.hfig = figure;
        set(data.hfig, 'Color', 'w', 'Name', 'qvPaired', ...
            'NumberTitle', 'off', 'Position', [360    55   560   657]);
    case 'select new file'
        data = get(gcf, 'UserData');
        saveCurrentDirectory = pwd;
        pathstr = fileparts(data.completename);
        cd(pathstr);
        [filename, pathname] = uigetfile('*.xsg', 'Select an XSG trace');
        if isequal(filename,0) || isequal(pathname,0)
            return
        end
        fullfilename = fullfile(pathname, filename);
        [pathstr, tracename, ext, versn] = fileparts(fullfilename);
        data.completename = fullfile(pathstr, [tracename, ext, versn]);
        cd(saveCurrentDirectory)
        clf;
    case 'scroll backwards'
        data = get(gcf, 'UserData');
        clf;
        [pathstr, tracename, ext] = fileparts(data.completename);
        fullfile(pathstr, ['*' ext]);
        traceFiles = dir(fullfile(pathstr, ['*' ext]));
        c = struct2cell(traceFiles);
        list = char(c{1,:});
        k = strmatch(tracename, list);
        if k > 1
            newfilename = list(k-1,:); % file name of the preceding (k-1) file
            data.completename = fullfile(pathstr, newfilename);
            [pathstr, tracename] = fileparts(data.completename);
        end
    case 'scroll forwards'
        data = get(gcf, 'UserData');
        clf;
        [pathstr, tracename, ext] = fileparts(data.completename);
        fullfile(pathstr, ['*' ext]);
        traceFiles = dir(fullfile(pathstr, ['*' ext]));
        c = struct2cell(traceFiles);
        list = char(c{1,:});
        k = strmatch(tracename, list);
        if k < size(list, 1)
            newfilename = list(k+1,:); % file name of the following (k+1) file
            data.completename = fullfile(pathstr, newfilename);
            [pathstr, tracename] = fileparts(data.completename);
        end
    case 'specific file'
        data = [];
        try
            cd(defaultDirectory);
        catch
            try
                cd('C:\Data');
            catch
                 disp('qvTrace: unable to find default dir.')
            end
        end
        fullfilename = varargin{2};
        [pathstr, tracename, ext, versn] = fileparts(fullfilename);
        data.completename = fullfile(pathstr, [tracename, ext, versn]);
        data.hfig = figure;
        set(data.hfig, 'Color', 'w', 'Name', 'qvTrace', ...
            'NumberTitle', 'off', 'Position', [360    55   560   657]);
end
set(data.hfig, 'UserData', data);

% open the file, extract the data
currentTrace = load(data.completename, '-mat');
currentTrace.userFcn.filename = data.completename;

% put the data in the workspace
assignin('base', 'currentTrace', currentTrace);

% store in figure's userData
data.currentTrace = currentTrace;
set(data.hfig, 'UserData', data);

% acquirer is not used in rig 4.
% % TODO: fix this temporary KLUGE
% if ~isfield(currentTrace.header.acquirer.acquirer, 'acqOnArray')
%     currentTrace.header.acquirer.acquirer.acqOnArray = 0;
% end

% determine what was acq'd and stim'd, and how
NacqEphys = currentTrace.header.ephys.ephys.startButton * ...
    sum(currentTrace.header.ephys.ephys.acqOnArray);
Nother = currentTrace.header.ephys.ephys.startButton * ...
    sum(currentTrace.header.ephys.ephys.stimOnArray);
%     currentTrace.header.acquirer.acquirer.startButton * ...
%     sum(currentTrace.header.acquirer.acquirer.acqOnArray) + ...
%     currentTrace.header.stimulator.stimulator.startButton * ...
%     sum(currentTrace.header.stimulator.stimulator.stimOnArray);

% decide subplot layout
Nsub = 2 * NacqEphys + Nother; % ephys traces count double
plotnum = 0;

% were data obtained by pulseJacker? (If so, different method for determining pulses)
pulseJackerFlag = currentTrace.header.pulseJacker.pulseJacker.enable; 
if pulseJackerFlag; 
    disp(' '); 
    disp('pulseJacker trace'); 
end

% who triggered whom:
% disp(' ');
% disp(['ephys startButton: ' num2str(currentTrace.header.ephys.ephys.startButton)]);
% disp(['acq startButton: ' num2str(currentTrace.header.acquirer.acquirer.startButton)]);
% disp(['stim startButton: ' num2str(currentTrace.header.stimulator.stimulator.startButton)]);
% disp(['ephys externalTrigger: ' num2str(currentTrace.header.ephys.ephys.externalTrigger)]);
% disp(['acq externalTrigger: ' num2str(currentTrace.header.acquirer.acquirer.externalTrigger)]);
% disp(['stim externalTrigger: ' num2str(currentTrace.header.stimulator.stimulator.externalTrigger)]);

% loop??: yes, if selfTrigger=0 for all started programs (startButton=1)
loopFlag = 0;
loopDaqFlag = 0;
loopCpuFlag = 0;
loopIterations = currentTrace.header.loopGui.loopGui.iterations;
loopIterationCounter = currentTrace.header.loopGui.loopGui.iterationCounter;
numberOfSelfTriggeringPrograms = currentTrace.header.ephys.ephys.startButton * currentTrace.header.ephys.ephys.selfTrigger;
% currentTrace.header.acquirer.acquirer.startButton * currentTrace.header.acquirer.acquirer.selfTrigger + ...
% currentTrace.header.stimulator.stimulator.startButton * currentTrace.header.stimulator.stimulator.selfTrigger;
if numberOfSelfTriggeringPrograms == 0
    loopFlag = 1;
    if currentTrace.header.loopGui.loopGui.cpuTiming
        loopCpuFlag = 1; 
        loopDaqFlag = 0;
    else
        loopCpuFlag = 0; 
        loopDaqFlag = 1;
    end
    loopIterations = currentTrace.header.loopGui.loopGui.iterations;
end
disp(['loopFlag: ' num2str(loopFlag) '; loopCpuFlag: ' num2str(loopCpuFlag) '; loopDaqFlag: ' num2str(loopDaqFlag) ...
    '; iterations: ' num2str(loopIterations) '; counter: ' num2str(loopIterationCounter)]);

currentTrace.userFcn.fIAnalysis.familyType = '';



% ============ EPHYS TRACES ==================
for channelNum = 1:NacqEphys
    if currentTrace.header.ephys.ephys.startButton && currentTrace.header.ephys.ephys.acqOnArray(channelNum) == 1;
        ephysdata = getfield(currentTrace.data.ephys,['trace_',num2str(channelNum)]);
        timedata = 0 : size(ephysdata, 1) - 1;
        timedata = timedata / currentTrace.header.ephys.ephys.sampleRate;
        plotnum = plotnum + 1;
        subplot(Nsub, 1, [plotnum plotnum+1]);
        plotnum = plotnum + 1; % double-high subplot for ephys traces
        
        % determine the time frame of displayed traces.
        if length(ephysdata) == 10000;
            data.traceBegin = 1;
            data.traceEnd = 10000;
        end
        
        if(~isfield(data,'traceBegin'))
            if(strcmp(inputdlg('change the time frame? (y/n)'),'y'))
                try
                    data.traceBegin = inputdlg('beginning point')
                    data.traceEnd = inputdlg('end point')
                    data.traceBegin = str2num(cell2mat(data.traceBegin));
                    data.traceEnd = str2num(cell2mat(data.traceEnd));
                catch
                    display('unexpected data. show entire traces')
                end
            end
        end
        
        try
            plot(timedata(data.traceBegin:data.traceEnd), ephysdata(data.traceBegin:data.traceEnd));
        catch
            plot(timedata, ephysdata);
        end    
        xlabel('Time (seconds)');
        ylabel('Amplitude');
        traceType = '';
        if loopFlag
            if loopCpuFlag
                traceType = [' -- cpu loop, iteration ' ...
                    num2str(loopIterationCounter) ' of ' num2str(loopIterations)];
                currentTrace.userFcn.fIAnalysis.familyType = 'cpu loop';
            elseif loopDaqFlag
                traceType = [' -- daq loop, all ' num2str(loopIterations) ' iterations'];
                currentTrace.userFcn.fIAnalysis.familyType = 'daq loop';
            end
        else
            currentTrace.userFcn.fIAnalysis.familyType = 'not a loop';
        end
        htitle = title([pathstr '\' tracename traceType]);
        set(htitle, 'Interpreter', 'none');
        box off;
        axis tight
    end

    % plot corresponding ephys stim pulse
    % TODO: determine timedata here, instead of relying on the above
    if currentTrace.header.ephys.ephys.startButton && currentTrace.header.ephys.ephys.stimOnArray(1) == 1;
        try % TODO: get rid of the try 
            traceLength = currentTrace.header.ephys.ephys.traceLength;
            if ~pulseJackerFlag
                params = currentTrace.header.ephys.ephys.pulseParameters{:};
                if isempty(params)
                    try
                        params = currentTrace.header.ephys.ephys.pulseParameters{2}; % probably wrong for 2nd chan
                    catch
                        disp('qvTrace: field pulseParameters is empty.')
                    end
                end
                % here's where the problem is. if there's only one amp channel,
                % there's only one index. but if there are two channels, the
                % first channel's pulse has index 2; index 1 is empty.
            else
                cp = currentTrace.header.pulseJacker.pulseJacker.currentPosition;
    %             np = size(currentTrace.header.pulseJacker.pulseJacker.positions{1}, 2);
    %             params = currentTrace.header.pulseJacker.pulseJacker.pulseDataMap{(cp-1)*np+1}(:);
                channelIndex = 1;
                params = currentTrace.header.pulseJacker.pulseJacker.pulseDataMap{channelIndex, cp + 1};
            end
            pulseTrace = pulseTraceFromParameters(params, traceLength);
            timedata = ((0 : currentTrace.header.ephys.ephys.sampleRate * currentTrace.header.ephys.ephys.traceLength - 1) / ...
                currentTrace.header.ephys.ephys.sampleRate)';
            if loopFlag && loopDaqFlag
    %             pulseTrace = repmat(pulseTrace, loopIterations, 1);
                pulseTrace = [];
                for n = 1 : loopIterations
                    np = size(currentTrace.header.pulseJacker.pulseJacker.positions{1}, 2);
                    params = currentTrace.header.pulseJacker.pulseJacker.pulseDataMap{(n-1)*np+1}(:);
                    pulseTracelet = pulseTraceFromParameters(params, traceLength);
                    pulseTrace = [pulseTrace; pulseTracelet];
                end
                size(pulseTracelet)
                size(pulseTrace)
                timedata = ((0 : currentTrace.header.ephys.ephys.sampleRate * currentTrace.header.ephys.ephys.traceLength ...
                    * loopIterations - 1) / currentTrace.header.ephys.ephys.sampleRate)';
            end
            plotnum = plotnum + 1;
            subplot(Nsub, 1, plotnum);
            hplot = plot(timedata, pulseTrace);
            set(hplot, 'LineWidth', 2, 'Color', 'r');
            xlabel('Time (seconds)');
            ylabel('Amplitude');
            htitle = title(['Pulse: ' params.name]);
            set(htitle, 'Interpreter', 'none');
            box off;
            axis tight
        catch
            disp('qvTrace: problem making ephys stim pulse.')
        end
    end
end

% update the data in the workspace
assignin('base', 'currentTrace', currentTrace);

% store in figure's userData
data.currentTrace = currentTrace;
set(data.hfig, 'UserData', data);

% update the data in the workspace
assignin('base', 'currentTrace', currentTrace);

% store in figure's userData
data.currentTrace = currentTrace;
set(data.hfig, 'UserData', data);

path = fileparts(which('qvPaired.m'));
if isdir([path '\private'])
    hmenu = uimenu('Parent', gcf, 'Label', 'UserFcns');
    s = dir([path '\private']);
    for n = 1 : size(s, 1)
        if ~s(n).isdir
            [a,b] = fileparts(s(n).name);
            uimenu('Parent', hmenu, 'Label', b, 'Callback', b)
        end
    end
end
addMenuToFigure(gcf, 'autoNotes', ...
    'Label', 'show autoNotes for current experiment', ...
    'callBack', 'showAutoNotesForTrace');
uicontrol('Style', 'pushbutton', 'String', '<<', 'Units', 'normalized', ...
    'Position', [.92 .93 .04 .07], 'Callback', 'qvPaired(''scroll backwards'')');
uicontrol('Style', 'pushbutton', 'String', '>>', 'Units', 'normalized', ...
    'Position', [.96 .93 .04 .07], 'Callback', 'qvPaired(''scroll forwards'')');
uicontrol('Style', 'pushbutton', 'String', 'New', 'Units', 'normalized', ...
    'Position', [.92 .86 .08 .07], 'Callback', 'qvPaired(''select new file'')');
uicontrol('Style', 'text', 'String', ...
    ['epoch ' num2str(currentTrace.header.xsg.xsg.epoch)], ...
    'Units', 'normalized', 'Position', [.01 .96 .1 .03]);